#include "WidgetMovimiento.h"
#include "../common/utils/FileChecker.h"
#include "../common/lib/SDL_rotozoom.h"


void WidgetMovimiento::initColorKey()
{
	if(surface != NULL){
	    //Le cambio el fondo de color
	    Uint32 colorkey;
	    colorkey = SDL_MapRGB(surface->format, 0, 255, 255);
	    SDL_SetColorKey( surface, SDL_SRCCOLORKEY, colorkey );
	}
}

WidgetMovimiento::WidgetMovimiento(int posX, int posY,std::string imagePath, Widget *parent)
:Widget(posX, posY,imagePath, parent) {
	drawable = true;
    initColorKey();

	surfaceShown = rotozoomSurface(this->surface, angle, 1.0,
					SMOOTHING_OFF);
}


WidgetMovimiento::WidgetMovimiento(int posX, int posY,int ancho, int alto,std::string imagePath, Widget* parent)
:Widget(posX, posY,imagePath, parent) {

	if (surface != NULL){
		SDL_Surface* newSurface = SurfaceUtils::resizeSurface(ancho,alto,surface);

		SDL_FreeSurface(surface);
		this->surface = newSurface;

		surfaceShown = rotozoomSurface(this->surface, angle, 1.0,
						SMOOTHING_OFF);
	}

	drawable = true;

	initColorKey();
}

bool WidgetMovimiento::isDrawable() {
	return drawable;
}

WidgetMovimiento::~WidgetMovimiento() {
	if(surfaceShown != NULL){
		SDL_FreeSurface(surfaceShown);
		surfaceShown = NULL;
	}
}

void WidgetMovimiento::surfaceReflection(SDL_Surface* objectSurface, SDL_Surface* screenSurface) {

	int screenWidth = screenSurface->w;
	int screenHeight = screenSurface->h;
	int objectWidth = objectSurface->w;
	int objectHeight = objectSurface->h;

	int topBorderIntersection = analyseBorderIntersection(TOP_BORDER, objectWidth, objectHeight, screenWidth, screenHeight);
	int bottomBorderIntersection = analyseBorderIntersection(BOTTOM_BORDER, objectWidth, objectHeight, screenWidth, screenHeight);
	int leftBorderIntersection = analyseBorderIntersection(LEFT_BORDER,	objectWidth, objectHeight, screenWidth, screenHeight);
	int rightBorderIntersection = analyseBorderIntersection(RIGHT_BORDER, objectWidth, objectHeight, screenWidth, screenHeight);

	// Position where the surface will be draw
	SDL_Rect posRectAux = { parcel->posX, parcel->posY, objectSurface->w,
			objectSurface->h };

	// Position fixed to the center of rotation
	posRectAux.x -= (objectSurface->w) / 2;
	posRectAux.y -= (objectSurface->h) / 2;

	//If the object is going out through the LEFT BORDER -> the object reflection will be analyzed
	if (leftBorderIntersection >= 0) {
		// If half object is over the left border the other half will be reflected on the right border
		if (leftBorderIntersection == 1) {
			SDL_Rect posRectCopy = posRectAux;
			posRectCopy.x += screenWidth;
			SDL_BlitSurface(objectSurface, NULL, screenSurface, &posRectCopy);

			if (topBorderIntersection == 1) {
				SDL_Rect posRectCopy = posRectAux;
				posRectCopy.x += screenWidth;
				posRectCopy.y += screenHeight;
				SDL_BlitSurface(objectSurface, NULL, screenSurface,
						&posRectCopy);
			} else if (bottomBorderIntersection == 1) {
				SDL_Rect posRectCopy = posRectAux;
				posRectCopy.x += screenWidth;
				posRectCopy.y -= screenHeight;
				SDL_BlitSurface(objectSurface, NULL, screenSurface,
						&posRectCopy);
			}
		}
	}
	//If the object is going out through the RIGHT BORDER -> the object reflection will be analyzed
	if (rightBorderIntersection >= 0) {
		if (rightBorderIntersection == 1) {
			SDL_Rect posRectCopy = posRectAux;
			posRectCopy.x -= screenWidth;
			SDL_BlitSurface(objectSurface, NULL, screenSurface, &posRectCopy);
			if (topBorderIntersection == 1) {
				SDL_Rect posRectCopy = posRectAux;
				posRectCopy.x -= screenWidth;
				posRectCopy.y += screenHeight;
				SDL_BlitSurface(objectSurface, NULL, screenSurface,
						&posRectCopy);
			} else if (bottomBorderIntersection == 1) {
				SDL_Rect posRectCopy = posRectAux;
				posRectCopy.x -= screenWidth;
				posRectCopy.y -= screenHeight;
				SDL_BlitSurface(objectSurface, NULL, screenSurface,
						&posRectCopy);
			}
		}

	}
	//If the object is going out through the TOP BORDER -> the object reflection will be analyzed
	if (topBorderIntersection >= 0) {
		// If half object is over the top border the other half will be reflected on the bottom border
		if (topBorderIntersection == 1) {
			SDL_Rect posRectCopy = posRectAux;
			posRectCopy.y += screenHeight;
			SDL_BlitSurface(objectSurface, NULL, screenSurface, &posRectCopy);
		}

	}
	//If the object is going out through the BOTTOM BORDER -> the object reflection will be analyzed
	if (bottomBorderIntersection >= 0) {
		// If half object is over the bottom border the other half will be reflected on the top border
		if (bottomBorderIntersection == 1) {
			SDL_Rect posRectCopy = posRectAux;
			posRectCopy.y -= screenHeight;
			SDL_BlitSurface(objectSurface, NULL, screenSurface, &posRectCopy);
		}
	}
}

int WidgetMovimiento::analyseBorderIntersection(borderType border, int surfaceWidth, int surfaceHeight, int screenWidth, int screenHeight) {
	int result = -1;
	int surfacePosY = parcel->posY - surfaceHeight / 2;
	int surfacePosX = parcel->posX - surfaceWidth / 2;
	switch (border) {
	case TOP_BORDER: {
		//If the dot is going out through the top border the dot reflection will be analyzed
		if (surfacePosY < 0) {
			// If half dot is over the top border the other half will be reflected on the bottom border
			if (surfacePosY + surfaceHeight > 0)
				result = 1;
			else
				result = 0;
		}
	}
		break;
	case BOTTOM_BORDER: {
		//If the dot is going out through the bottom border the dot reflection will be analyzed
		if (surfacePosY + surfaceHeight > screenHeight) {
			// If half dot is over the bottom border the other half will be reflected on the top border
			if (surfacePosY < screenHeight)
				result = 1;
			else
				result = 0;
		}
	}
		break;
	case RIGHT_BORDER: {
		//If the dot is going out through the right border the dot reflection will be analyzed
		if (surfacePosX + surfaceWidth > screenWidth) {
			// If half dot is over the right border the other half will be reflected on the left border
			if (surfacePosX < screenWidth)
				result = 1;
			else
				result = 0;
		}
	}
		break;
	case LEFT_BORDER: {
		//If the dot is going out through the left border the dot reflection will be analyzed
		if (surfacePosX < 0) {
			// If half dot is over the left border the other half will be reflected on the right border
			if (surfacePosX + surfaceWidth > 0)
				result = 1;
			else
				result = 0;
		}
	}
		break;
	}

	return result;
}

void WidgetMovimiento::positionCorrection(SDL_Surface* objectSurface) {
	if (parcel->posX > objectSurface->w)
		parcel->posX -= objectSurface->w;
	else if (parcel->posX < 0)
		parcel->posX += objectSurface->w;

	if (parcel->posY > objectSurface->h)
		parcel->posY -= objectSurface->h;
	else if (parcel->posY < 0)
		parcel->posY += objectSurface->h;
}

void WidgetMovimiento::showOn(SDL_Surface* canvasSurface) {

	if(drawable)
	{
		if(surfaceShown != NULL){
			SDL_FreeSurface(surfaceShown);
			surfaceShown = NULL;
		}
		surfaceShown = rotozoomSurface(this->surface, angle, 1.0,
				SMOOTHING_OFF);

		positionCorrection(canvasSurface);

	//	//Surface Reflection
		surfaceReflection(surfaceShown, canvasSurface);

		// Position where the surface will be draw
		SDL_Rect posRect = { parcel->posX, parcel->posY, surfaceShown->w,
				surfaceShown->h };

		// Position fixed to the center of rotation
		posRect.x -= (surfaceShown->w) / 2;
		posRect.y -= (surfaceShown->h) / 2;

		//Show the original dot
		SDL_BlitSurface(surfaceShown, NULL, canvasSurface, &posRect);
	}
}

bool WidgetMovimiento::checkCollision(WidgetMovimiento* widgetMov){
	// Position where the surface will be draw
	SDL_Rect posRectA = this->getRectangle();

	SDL_Rect posRectB = widgetMov->getRectangle();

	SDL_Rect collisionRect = SurfaceUtils::intersection(posRectA, posRectB);

	if(collisionRect.w == 0 && collisionRect.h == 0)
		return false;

	// Por ahora no normaliza (habría que "estirar" los rectangulos para que evaluen un poco más de superficie)
	SDL_Rect normalA = posRectA; //this->NormalizeBounds(collisionRect);
	SDL_Rect normalB = posRectB; //widgetMov->NormalizeBounds(collisionRect);

	for(int y = 0; y <= collisionRect.h; y++)
		for(int x = 0; x <= collisionRect.w; x++)
			if(SurfaceUtils::getAlphaXY(this->surfaceShown, normalA.x + x, normalA.y + y) && SurfaceUtils::getAlphaXY(widgetMov->surfaceShown, normalB.x + x, normalB.y + y))
				return true;

	return false;
}

SDL_Rect WidgetMovimiento::getRectangle(){
	// Position where the surface will be draw
	SDL_Rect posRect;
	posRect.x = parcel->posX - (surfaceShown->w) / 2;
	posRect.y = parcel->posY - (surfaceShown->h) / 2;
	posRect.w = surfaceShown->w;
	posRect.h = surfaceShown->h;

	return posRect;
}
